package com.connector.server.server;

import org.slf4j.LoggerFactory;
import com.connector.server.redis.OnLineUserCache;
import com.connector.base.connection.impl.NettyConnection;
import com.connector.base.protocol.Packet;
import com.connector.base.connection.Connection;
import com.connector.base.codec.PacketDecoder;
import com.connector.base.connection.channel.SocketChannel;
import com.connector.base.connection.channel.NettyChannelSocketChannel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.channel.ChannelHandlerContext;
import com.connector.base.message.PacketReceiver;
import com.connector.base.connection.ConnectionRegistry;
import org.slf4j.Logger;
import io.netty.channel.ChannelHandler;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.channel.SimpleChannelInboundHandler;

@ChannelHandler.Sharable
public class WebSocketChannelHandler extends SimpleChannelInboundHandler<WebSocketFrame>
{
    private static final Logger log;
    private final ConnectionRegistry connectionRegistry;
    private final PacketReceiver receiver;
    
    public WebSocketChannelHandler(final ConnectionRegistry connectionRegistry, final PacketReceiver receiver) {
        this.connectionRegistry = connectionRegistry;
        this.receiver = receiver;
    }
    
    protected void channelRead0(final ChannelHandlerContext ctx, final WebSocketFrame frame) {
        if (!(frame instanceof TextWebSocketFrame)) {
            throw new UnsupportedOperationException(String.format("unsupported frame type: " + frame.getClass().getName(), new Object[0]));
        }
        final String text = ((TextWebSocketFrame)frame).text();
        final Connection connection = this.connectionRegistry.get((SocketChannel)new NettyChannelSocketChannel(ctx.channel()));
        final Packet packet = PacketDecoder.decodeFrame(text);
        if (null == packet) {
            return;
        }
        WebSocketChannelHandler.log.debug("channelRead conn={}, packet={}", new Object[] { ctx.channel(), connection.getSessionContext(), packet });
        this.receiver.onReceive(packet, connection);
    }
    
    public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) {
        final Connection connection = this.connectionRegistry.get((SocketChannel)new NettyChannelSocketChannel(ctx.channel()));
        WebSocketChannelHandler.log.error("client caught ex, conn={}", (Object)connection, (Object)cause);
        ctx.close();
    }
    
    public void channelActive(final ChannelHandlerContext ctx) {
        WebSocketChannelHandler.log.info("websocketclient connected conn={}", (Object)ctx.channel());
        final Connection connection = (Connection)new NettyConnection();
        connection.init((SocketChannel)new NettyChannelSocketChannel(ctx.channel()));
        this.connectionRegistry.add(connection);
    }
    
    public void channelInactive(final ChannelHandlerContext ctx) {
        final Connection connection = this.connectionRegistry.removeAndClose((SocketChannel)new NettyChannelSocketChannel(ctx.channel()));
        if (null != connection && null != connection.getSessionContext()) {
            final String userId = connection.getSessionContext().getUserId();
            OnLineUserCache.del(userId);
            WebSocketChannelHandler.log.info("socket连接断开:{}", (Object)userId);
        }
        else {
            WebSocketChannelHandler.log.info("socket连接断开");
        }
    }
    
    static {
        log = LoggerFactory.getLogger((Class)WebSocketChannelHandler.class);
    }
}
